package com.xyazm.fulfill.service.impl;

import com.xyazm.common.enums.OrderStatusChangeEnum;
import com.xyazm.common.utils.JsonUtil;
import com.xyazm.fulfill.dao.OrderFulfillDAO;
import com.xyazm.fulfill.domain.entity.OrderFulfillDO;
import com.xyazm.fulfill.domain.entity.OrderFulfillItemDO;
import com.xyazm.fulfill.domain.event.OrderDeliveredEvent;
import com.xyazm.fulfill.domain.event.OrderOutStockEvent;
import com.xyazm.fulfill.domain.param.TriggerOrderAfterFulfillEventParam;
import com.xyazm.fulfill.event.OrderAfterFulfillEventProcessor;
import com.xyazm.fulfill.event.WmsShipEventProcessorFactory;
import com.xyazm.fulfill.mapstruct.FulfillApiMapstruct;
import com.xyazm.fulfill.remote.TmsRemote;
import com.xyazm.fulfill.remote.WmsRemote;
import com.xyazm.fulfill.service.IFulfillScheduleService;
import com.xyazm.tms.domain.dto.SendOutDTO;
import com.xyazm.tms.domain.param.SendOutParam;
import com.xyazm.wms.domain.param.PickGoodsParam;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.List;


@Slf4j
@Service
public class FulfillScheduleServiceImpl implements IFulfillScheduleService {

    @Autowired
    private TmsRemote tmsRemote;
    @Autowired
    private WmsRemote wmsRemote;

    @Autowired
    private OrderFulfillDAO orderFulfillDAO;
    @Autowired
    private WmsShipEventProcessorFactory wmsShipEventProcessorFactory;


    @Override
    public void doSchedule(OrderFulfillDO orderFulfill, List<OrderFulfillItemDO> orderFulfillItems) {
        // mock触发仓储打包出库，触发物流配送，签收

        // 1.调用wms的接口进行仓储捡货
        wmsRemote.pickGoods(buildPickGoodsParam(orderFulfill, orderFulfillItems));

        // 2.处理发送订单已出库消息
        processSendOrderOutStockEvent(orderFulfill);

        // 3.调用tms的接口进行发货
        SendOutDTO sendOutResult = tmsRemote.sendOut(buildSendOutParam(orderFulfill, orderFulfillItems));
        log.info("发货结果，result={}", JsonUtil.object2Json(sendOutResult));

        // 4.存储物流单号
        String logisticsCode = sendOutResult.getLogisticsCode();
        orderFulfillDAO.saveLogisticsCode(orderFulfill.getFulfillId(), logisticsCode);

        // 5.处理发送订单已配送消息
        processSendOrderDeliveredEvent(orderFulfill, sendOutResult);

    }

    /**
     * 构造发货请求
     */
    private SendOutParam buildSendOutParam(OrderFulfillDO orderFulfill, List<OrderFulfillItemDO> orderFulfillItems) {
        SendOutParam sendOutParam = FulfillApiMapstruct.INSTANCE.convertSendOutParam(orderFulfill);
        List<SendOutParam.OrderItemParam> orderItemParams = FulfillApiMapstruct.INSTANCE.convertSendOutOrderItemParamList(orderFulfillItems);
        sendOutParam.setOrderItems(orderItemParams);
        return sendOutParam;
    }


    /**
     * 构造捡货请求
     */
    private PickGoodsParam buildPickGoodsParam(OrderFulfillDO orderFulfill, List<OrderFulfillItemDO> orderFulfillItems) {
        PickGoodsParam pickGoodsParam = FulfillApiMapstruct.INSTANCE.convertPickGoodsParam(orderFulfill);
        List<PickGoodsParam.OrderItemParam> orderItemParams =
                FulfillApiMapstruct.INSTANCE.convertPickGoodsOrderItemParamList(orderFulfillItems);
        pickGoodsParam.setOrderItems(orderItemParams);
        return pickGoodsParam;
    }

    /**
     * 处理发送订单已出库消息
     * @author xuyou
     * 2023-02-13 21:08
     * @param orderFulfillDO
     */
    private void processSendOrderOutStockEvent(OrderFulfillDO orderFulfillDO) {
        OrderStatusChangeEnum orderStatusChangeEnum = OrderStatusChangeEnum.ORDER_OUT_STOCKED;
        OrderAfterFulfillEventProcessor wmsShipEventProcessor =
                wmsShipEventProcessorFactory.getWmsShipEventProcessor(orderStatusChangeEnum);

        // 设置出库事件
        OrderOutStockEvent orderOutStockEvent = new OrderOutStockEvent();
        orderOutStockEvent.setOutStockTime(new Date());

        // 触发订单履约后置事件请求
        TriggerOrderAfterFulfillEventParam triggerOrderAfterFulfillEvent =
                new TriggerOrderAfterFulfillEventParam();
        triggerOrderAfterFulfillEvent.setOrderId(orderFulfillDO.getOrderId());
        triggerOrderAfterFulfillEvent.setFulfillId(orderFulfillDO.getFulfillId());
        triggerOrderAfterFulfillEvent.setOrderStatusChange(orderStatusChangeEnum);
        triggerOrderAfterFulfillEvent.setAfterFulfillEvent(orderOutStockEvent);

        // 执行订单履约后置事件 - 已出库
        wmsShipEventProcessor.execute(triggerOrderAfterFulfillEvent,orderFulfillDO);
    }

    /**
     * 处理发送订单已配送消息
     */
    private void processSendOrderDeliveredEvent(OrderFulfillDO orderFulfillDO, SendOutDTO sendOutDTO) {
        OrderStatusChangeEnum orderStatusChangeEnum = OrderStatusChangeEnum.ORDER_DELIVERED;
        OrderAfterFulfillEventProcessor wmsShipEventProcessor =
                wmsShipEventProcessorFactory.getWmsShipEventProcessor(orderStatusChangeEnum);

        // 设置配送员信息
        OrderDeliveredEvent orderDeliveredEvent = new OrderDeliveredEvent();
        orderDeliveredEvent.setDelivererNo(sendOutDTO.getDelivererNo());
        orderDeliveredEvent.setDelivererName(sendOutDTO.getDelivererName());
        orderDeliveredEvent.setDelivererPhone(sendOutDTO.getDelivererPhone());

        // 触发订单履约后置事件请求
        TriggerOrderAfterFulfillEventParam triggerOrderAfterFulfillEvent =
                new TriggerOrderAfterFulfillEventParam();
        triggerOrderAfterFulfillEvent.setOrderId(orderFulfillDO.getOrderId());
        triggerOrderAfterFulfillEvent.setFulfillId(orderFulfillDO.getFulfillId());
        triggerOrderAfterFulfillEvent.setOrderStatusChange(orderStatusChangeEnum);
        triggerOrderAfterFulfillEvent.setAfterFulfillEvent(orderDeliveredEvent);

        // 执行订单履约后置事件 - 已配送
        wmsShipEventProcessor.execute(triggerOrderAfterFulfillEvent, orderFulfillDO);
    }

}
